Skip to content

implement ResourceList component with agencies pages (DEV-77)#14

Open
ivymxu wants to merge 4 commits intomainfrom
feature/DEV-77/resourcelist
Open

implement ResourceList component with agencies pages (DEV-77)#14
ivymxu wants to merge 4 commits intomainfrom
feature/DEV-77/resourcelist

Conversation

@ivymxu
Copy link

@ivymxu ivymxu commented Feb 24, 2026

Jira ticket link

DEV-77

Implementation description

  • Add reusable ResourceList component with loading/empty/error states
  • Refactor /agencies page and add detail/edit pages
  • Create apiClient utility for typed API requests

Steps to test

  1. Navigate to http://localhost:3000/agencies
  2. Verify the table renders with columns: Name, Email, Phone, City, Status
  3. Test View action → /agencies/ shows agency details
  4. Test Edit action → /agencies//edit shows form with save functionality
  5. Test empty state by seeding no agencies
  6. Verify loading skeleton appears while data loads

What should reviewers focus on?

  • ResourceList component is generic and reusable
  • Column/action configuration is extensible for other resources (clients, donors, etc)
  • Cell rendering: email/phone are linkified, status badges are color-coded
  • Tests cover critical paths: rendering, loading, empty, error, actions
  • API client properly handles request/response interceptors
  • Error handling in detail/edit pages and form mutations

Checklist

Format for branch, commit, and PR title: docs/GIT.md.

  • My branch name includes the Jira ticket key
  • My PR name is descriptive and in imperative tense
  • My PR name includes the Jira ticket key
  • My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits
  • My commit messages include the Jira ticket key
  • I have run the appropriate linter(s)
  • I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR

@ivymxu ivymxu force-pushed the feature/DEV-77/resourcelist branch from ea7e9ce to c27853f Compare February 27, 2026 01:00
@ivymxu ivymxu requested review from kenzysoror and sonya-q February 27, 2026 01:04
@ivymxu ivymxu force-pushed the feature/DEV-77/resourcelist branch from cbf380b to a117e60 Compare February 27, 2026 01:08
@ivymxu ivymxu marked this pull request as ready for review February 27, 2026 01:09
@nuthanan06 nuthanan06 assigned nuthanan06 and ivymxu and unassigned nuthanan06 Mar 6, 2026
@kenzysoror kenzysoror requested review from nuthanan06 and removed request for sonya-q March 6, 2026 13:22
Copy link
Contributor

@nuthanan06 nuthanan06 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a couple changes on moving some things into other files + delete hasn't been implemented yet, otherwise lgtm! 🔥

Copilot AI review requested due to automatic review settings March 10, 2026 00:17
@ivymxu ivymxu force-pushed the feature/DEV-77/resourcelist branch from a117e60 to 6e79ad6 Compare March 10, 2026 00:17

This comment was marked as resolved.

@ivymxu ivymxu force-pushed the feature/DEV-77/resourcelist branch from 6e79ad6 to 784e365 Compare March 10, 2026 00:23
@uwblueprint uwblueprint deleted a comment from Copilot AI Mar 10, 2026
@ivymxu ivymxu force-pushed the feature/DEV-77/resourcelist branch from 784e365 to d49f48b Compare March 10, 2026 00:46
@uwblueprint uwblueprint deleted a comment from Copilot AI Mar 10, 2026
@uwblueprint uwblueprint deleted a comment from Copilot AI Mar 10, 2026
@ivymxu ivymxu force-pushed the feature/DEV-77/resourcelist branch from 435bec2 to 1a294e2 Compare March 10, 2026 00:51
@uwblueprint uwblueprint deleted a comment from Copilot AI Mar 10, 2026
Copy link
Member

@kenzysoror kenzysoror left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

beautiful work, ivy!!😍


case "text":
default:
return value != null ? String(value) : "—";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this is the only branch that returns a plain string instead of JSX, potentially wrap (<>{value != null ? String(value) : "—"}</>) so it's consistent with the other cases

import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useAgency } from "@/hooks/useApi";
import type { Agency } from "@/types";
Copy link
Member

@kenzysoror kenzysoror Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like Agency isn't used and should be safe to remove

return (
<div className="w-full" data-testid={testId}>
{/* Error State */}
{error && (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a failed request is retried, error and loading might both be true at the same time - can we add && !loading to avoid rendering both states at the same time

export default function AgencyEditPage() {
const params = useParams();
const router = useRouter();
const agencyId = params.id as string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider checking that params.id is a non-empty string before using it, and explicitly handle missing/invalid cases (e.g. render an error) instead of just casting

export default function AgencyDetailPage() {
const params = useParams();
const router = useRouter();
const agencyId = params.id as string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same params.id comment as left in frontend/app/agencies/[id]/edit/page.tsx

Comment on lines +42 to +49
<div className="min-h-screen flex flex-col">
<header className="w-full bg-gradient-to-r from-blue-600 to-blue-800 text-white shadow-lg">
<div className="max-w-6xl mx-auto px-6 py-6 flex justify-between items-center">
<h1 className="text-2xl font-bold">Loading…</h1>
<button
onClick={() => router.back()}
className="px-4 py-2 bg-white/20 rounded hover:bg-white/30 transition"
>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we seem to be duplicating the full page layout multiple times in this file - let's extract a shared layout component


if (isLoading) {
return (
<div className="min-h-screen flex flex-col">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same layout duplication as in frontend/app/agencies/[id]/edit/page.tsx

beforeEach(() => {
(useAgencies as jest.Mock).mockReset();
(useDeleteAgency as jest.Mock).mockReturnValue({ mutate: jest.fn() });
jest.spyOn(global, "confirm").mockReturnValue(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't look like we ever restore the confirm spy - let's add something like afterEach(() => jest.restoreAllMocks()) to prevent the mock from leaking into other tests

Comment on lines +109 to +110
},
staleTime: 1000 * 60 * 5,
Copy link
Member

@kenzysoror kenzysoror Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
},
staleTime: 1000 * 60 * 5,
},
enabled: Boolean(agencyId),
staleTime: 1000 * 60 * 5,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should tell the query to wait until there's a real value before making any network calls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants